/**
 * This file is Copyright © 2008 Software Craftsmen Limited. All Rights Reserved.
 */
package com.softwarecraftsmen.orogeny.actions;

import com.softwarecraftsmen.archivers.Archiver;
import com.softwarecraftsmen.orogeny.buildEnvironments.BuildEnvironment;
import com.softwarecraftsmen.orogeny.buildLogs.BuildLog;
import static com.softwarecraftsmen.orogeny.buildLogs.Verbosity.Summary;
import com.softwarecraftsmen.orogeny.execution.SuccessOrFailure;
import static com.softwarecraftsmen.orogeny.execution.SuccessOrFailure.Failure;
import static com.softwarecraftsmen.orogeny.execution.SuccessOrFailure.Success;
import com.softwarecraftsmen.orogeny.filing.AbsoluteDirectories;
import static com.softwarecraftsmen.orogeny.filing.AbsoluteDirectories.absoluteDirectories;
import com.softwarecraftsmen.orogeny.filing.AbsoluteDirectory;
import com.softwarecraftsmen.orogeny.filing.AbsoluteFile;
import com.softwarecraftsmen.orogeny.filing.findFileFilters.FindFilesFilter;
import org.jetbrains.annotations.NotNull;

import java.io.IOException;
import static java.lang.String.format;
import static java.util.Locale.UK;

public class ArchiveAction extends AbstractAction
{
	private final Archiver archiver;
	private final AbsoluteFile archiveFile;
	private final AbsoluteDirectories archiveRoots;
	private final FindFilesFilter findFilesFilter;

	public ArchiveAction(final @NotNull Archiver archiver, final @NotNull AbsoluteFile archiveFile, final @NotNull AbsoluteDirectories archiveRoots, final @NotNull FindFilesFilter findFilesFilter)
	{
		this.archiver = archiver;
		this.archiveFile = archiveFile;
		this.archiveRoots = archiveRoots;
		this.findFilesFilter = findFilesFilter;
	}

	@NotNull
	public String describeWhatWeDo()
	{
		return "archiveAs";
	}

	@NotNull
	public SuccessOrFailure execute(final @NotNull BuildLog buildLog, final @NotNull BuildEnvironment buildEnvironment)
	{
		if (archiveFile.exists())
		{
			return Failure(format(UK, "The archive file %1$s already exists", archiveFile));
		}
		buildLog.writeMessage(Summary, format(UK, "About to create a %1$s archive at %2$s using roots %3$s including %4$s", archiver, archiveFile, archiveRoots, findFilesFilter));

		try
		{
			archiver.archive(archiveFile, archiveRoots, findFilesFilter);
		}
		catch (IOException e)
		{
			return Failure(e);
		}

		return Success;
	}

	@NotNull
	public static SpecifyArchiver archiveAs(final @NotNull Archiver archiver)
	{
		return new SpecifyArchiver(archiver);
	}

	public static final class SpecifyArchiver
	{
		private Archiver archiver;

		private SpecifyArchiver(final @NotNull Archiver archiver)
		{
			this.archiver = archiver;
		}

		@NotNull
		public SpecifyTo to(final @NotNull AbsoluteFile archiveFile)
		{
			return new SpecifyTo(archiveFile);
		}

		public final class SpecifyTo
		{
			private final AbsoluteFile archiveFile;

			private SpecifyTo(final @NotNull AbsoluteFile archiveFile)
			{
				this.archiveFile = archiveFile;
			}

			@NotNull
			public SpecifyArchiveRoots roots(final @NotNull AbsoluteDirectory... archiveRoots)
			{
				return new SpecifyArchiveRoots(absoluteDirectories(archiveRoots));
			}

			@NotNull
			public SpecifyArchiveRoots roots(final @NotNull AbsoluteDirectories... archiveRoots)
			{
				return new SpecifyArchiveRoots(absoluteDirectories(archiveRoots));
			}

			public class SpecifyArchiveRoots
			{
				private final AbsoluteDirectories archiveRoots;

				private SpecifyArchiveRoots(final @NotNull AbsoluteDirectories archiveRoots)
				{
					this.archiveRoots = archiveRoots;
				}

				@NotNull
				public ArchiveAction capturing(final @NotNull FindFilesFilter findFilesFilter)
				{
					return new ArchiveAction(archiver, archiveFile, archiveRoots, findFilesFilter);
				}
			}
		}
	}
}
